package com.ruoyi.huanjing.test;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.List;

/**
 * 海洋电磁特性二进制文件解析器
 * 支持解析：平均散射系数、时变散射系数、幅度概率密度、时间相关特性、距离相关特性、多普勒谱、一维图像、距离-脉冲、时变多普勒谱
 *
 * @author 你的名字
 * @date 2025-07-29
 */
public class SeaEMDataParser {

    // 文件路径
    private final String filePath;
    // 文件字节数据
    private byte[] fileData;
    // 字节序（默认小端）
    private ByteOrder byteOrder = ByteOrder.LITTLE_ENDIAN;

    // 解析结果封装
    private SeaEMParseResult result;

    /**
     * 构造方法
     *
     * @param filePath 文件路径
     */
    public SeaEMDataParser(String filePath) {
        this.filePath = filePath;
    }

    /**
     * 设置字节序（大端/小端）
     *
     * @param byteOrder 字节序
     */
    public void setByteOrder(ByteOrder byteOrder) {
        this.byteOrder = byteOrder;
    }

    /**
     * 读取文件内容到字节数组
     *
     * @return 是否读取成功
     */
    public boolean readFile() {
        try (FileInputStream fis = new FileInputStream(filePath);
             ByteArrayOutputStream bos = new ByteArrayOutputStream()) {

            byte[] buffer = new byte[8192];
            int bytesRead;
            while ((bytesRead = fis.read(buffer)) != -1) {
                bos.write(buffer, 0, bytesRead);
            }
            fileData = bos.toByteArray();
            System.out.printf("文件读取成功，大小: %d 字节%n", fileData.length);
            return true;

        } catch (IOException e) {
            System.err.println("读取文件失败: " + e.getMessage());
            return false;
        }
    }

    /**
     * 解析整个文件数据
     *
     * @return 解析结果（失败返回 null）
     */
    public SeaEMParseResult parse() {
        if (fileData == null) {
            System.err.println("请先调用 readFile 方法读取文件数据");
            return null;
        }

        ByteBuffer buffer = ByteBuffer.wrap(fileData).order(byteOrder);
        result = new SeaEMParseResult();

        try {
            // 1. 解析【平均散射系数】
            parseAverageScatteringCoefficient(buffer);
            // 2. 解析【时变散射系数】
            parseTimeVaryingScatteringCoefficient(buffer);
            // 3. 解析【幅度概率密度】
            parseAmplitudeProbabilityDensity(buffer);
            // 4. 解析【时间相关特性】
            parseTimeCorrelation(buffer);
            // 5. 解析【距离相关特性】
            parseDistanceCorrelation(buffer);
            // 6. 解析【多普勒谱】
            parseDopplerSpectrum(buffer);
            // 7. 解析【一维图像】
            parseOneDimensionalImage(buffer);
            // 8. 解析【距离-脉冲】
            parseRangePulse(buffer);
            // 9. 解析【时变多普勒谱】
            parseTimeVaryingDopplerSpectrum(buffer);

            return result;

        } catch (Exception e) {
            System.err.println("解析文件数据失败: " + e.getMessage());
            return null;
        }
    }

    // ===================== 具体解析方法 =====================

    /**
     * 解析【平均散射系数】
     *
     * @param buffer ByteBuffer
     */
    private void parseAverageScatteringCoefficient(ByteBuffer buffer) {
        int n = buffer.getInt(); // 数据长度 N
        List<Double> data = new ArrayList<>(2 * n);
        for (int i = 0; i < 2 * n; i++) {
            data.add(buffer.getDouble());
        }
        result.setAverageScatteringCoefficient(n, data);
    }

    /**
     * 解析【时变散射系数】
     *
     * @param buffer ByteBuffer
     */
    private void parseTimeVaryingScatteringCoefficient(ByteBuffer buffer) {
        int n = buffer.getInt(); // 数据长度 N
        List<Double> data = new ArrayList<>(2 * n);
        for (int i = 0; i < 2 * n; i++) {
            data.add(buffer.getDouble());
        }
        result.setTimeVaryingScatteringCoefficient(n, data);
    }

    /**
     * 解析【幅度概率密度】
     *
     * @param buffer ByteBuffer
     */
    private void parseAmplitudeProbabilityDensity(ByteBuffer buffer) {
        int n = buffer.getInt(); // 数据长度 N
        List<Double> data = new ArrayList<>(2 * n);
        for (int i = 0; i < 2 * n; i++) {
            data.add(buffer.getDouble());
        }
        result.setAmplitudeProbabilityDensity(n, data);
    }

    /**
     * 解析【时间相关特性】
     *
     * @param buffer ByteBuffer
     */
    private void parseTimeCorrelation(ByteBuffer buffer) {
        int n = buffer.getInt(); // 数据长度 N
        List<Double> data = new ArrayList<>(2 * n);
        for (int i = 0; i < 2 * n; i++) {
            data.add(buffer.getDouble());
        }
        result.setTimeCorrelation(n, data);
    }

    /**
     * 解析【距离相关特性】
     *
     * @param buffer ByteBuffer
     */
    private void parseDistanceCorrelation(ByteBuffer buffer) {
        int n = buffer.getInt(); // 数据长度 N
        List<Double> data = new ArrayList<>(2 * n);
        for (int i = 0; i < 2 * n; i++) {
            data.add(buffer.getDouble());
        }
        result.setDistanceCorrelation(n, data);
    }

    /**
     * 解析【多普勒谱】
     *
     * @param buffer ByteBuffer
     */
    private void parseDopplerSpectrum(ByteBuffer buffer) {
        int n = buffer.getInt(); // 数据长度 N
        List<Double> data = new ArrayList<>(2 * n);
        for (int i = 0; i < 2 * n; i++) {
            data.add(buffer.getDouble());
        }
        result.setDopplerSpectrum(n, data);
    }

    /**
     * 解析【一维图像】
     *
     * @param buffer ByteBuffer
     */
    private void parseOneDimensionalImage(ByteBuffer buffer) {
        int n = buffer.getInt(); // 数据长度 N
        List<Double> data = new ArrayList<>(2 * n);
        for (int i = 0; i < 2 * n; i++) {
            data.add(buffer.getDouble());
        }
        result.setOneDimensionalImage(n, data);
    }

    /**
     * 解析【距离-脉冲】
     *
     * @param buffer ByteBuffer
     */
    private void parseRangePulse(ByteBuffer buffer) {
        // 距离门数据
        int m = buffer.getInt(); // 距离门长度 M
        List<Double> rangeGateData = new ArrayList<>(m);
        for (int i = 0; i < m; i++) {
            rangeGateData.add(buffer.getDouble());
        }

        // 脉冲数数据
        int n = buffer.getInt(); // 脉冲数长度 N
        List<Double> pulseData = new ArrayList<>(n);
        for (int i = 0; i < n; i++) {
            pulseData.add(buffer.getDouble());
        }

        // 数据实部 + 虚部（M*N 个）
        List<Double> realParts = new ArrayList<>(m * n);
        List<Double> imagParts = new ArrayList<>(m * n);
        for (int i = 0; i < m * n; i++) {
            realParts.add(buffer.getDouble());
        }
        for (int i = 0; i < m * n; i++) {
            imagParts.add(buffer.getDouble());
        }

        result.setRangePulse(m, n, rangeGateData, pulseData, realParts, imagParts);
    }

    /**
     * 解析【时变多普勒谱】
     *
     * @param buffer ByteBuffer
     */
    private void parseTimeVaryingDopplerSpectrum(ByteBuffer buffer) {
        // 多普勒频率数据
        int p = buffer.getInt(); // 频率长度 P
        List<Double> dopplerFreqData = new ArrayList<>(p);
        for (int i = 0; i < p; i++) {
            dopplerFreqData.add(buffer.getDouble());
        }

        // 时间数据
        int q = buffer.getInt(); // 时间长度 Q
        List<Double> timeData = new ArrayList<>(q);
        for (int i = 0; i < q; i++) {
            timeData.add(buffer.getDouble());
        }

        // 多普勒谱密度数据（P*Q 个）
        List<Double> spectrumData = new ArrayList<>(p * q);
        for (int i = 0; i < p * q; i++) {
            spectrumData.add(buffer.getDouble());
        }

        result.setTimeVaryingDopplerSpectrum(p, q, dopplerFreqData, timeData, spectrumData);
    }

    // ===================== 解析结果封装类 =====================

    /**
     * 解析结果封装类
     * 包含所有电磁特性数据
     */
    public static class SeaEMParseResult {
        // 平均散射系数
        private int averageScatteringCoefficientLength;
        private List<Double> averageScatteringCoefficientData;

        // 时变散射系数
        private int timeVaryingScatteringCoefficientLength;
        private List<Double> timeVaryingScatteringCoefficientData;

        // 幅度概率密度
        private int amplitudeProbabilityDensityLength;
        private List<Double> amplitudeProbabilityDensityData;

        // 时间相关特性
        private int timeCorrelationLength;
        private List<Double> timeCorrelationData;

        // 距离相关特性
        private int distanceCorrelationLength;
        private List<Double> distanceCorrelationData;

        // 多普勒谱
        private int dopplerSpectrumLength;
        private List<Double> dopplerSpectrumData;

        // 一维图像
        private int oneDimensionalImageLength;
        private List<Double> oneDimensionalImageData;

        // 距离-脉冲
        private int rangeGateLength;
        private int pulseCountLength;
        private List<Double> rangeGateData;
        private List<Double> pulseData;
        private List<Double> rangePulseRealParts;
        private List<Double> rangePulseImagParts;

        // 时变多普勒谱
        private int dopplerFreqLength;
        private int timeLength;
        private List<Double> dopplerFreqData;
        private List<Double> timeData;
        private List<Double> timeVaryingDopplerSpectrumData;

        // ----------------- Setter 方法 -----------------
        public void setAverageScatteringCoefficient(int length, List<Double> data) {
            this.averageScatteringCoefficientLength = length;
            this.averageScatteringCoefficientData = data;
        }

        public void setTimeVaryingScatteringCoefficient(int length, List<Double> data) {
            this.timeVaryingScatteringCoefficientLength = length;
            this.timeVaryingScatteringCoefficientData = data;
        }

        public void setAmplitudeProbabilityDensity(int length, List<Double> data) {
            this.amplitudeProbabilityDensityLength = length;
            this.amplitudeProbabilityDensityData = data;
        }

        public void setTimeCorrelation(int length, List<Double> data) {
            this.timeCorrelationLength = length;
            this.timeCorrelationData = data;
        }

        public void setDistanceCorrelation(int length, List<Double> data) {
            this.distanceCorrelationLength = length;
            this.distanceCorrelationData = data;
        }

        public void setDopplerSpectrum(int length, List<Double> data) {
            this.dopplerSpectrumLength = length;
            this.dopplerSpectrumData = data;
        }

        public void setOneDimensionalImage(int length, List<Double> data) {
            this.oneDimensionalImageLength = length;
            this.oneDimensionalImageData = data;
        }

        public void setRangePulse(int rangeGateLength, int pulseCountLength,
                                  List<Double> rangeGateData, List<Double> pulseData,
                                  List<Double> realParts, List<Double> imagParts) {
            this.rangeGateLength = rangeGateLength;
            this.pulseCountLength = pulseCountLength;
            this.rangeGateData = rangeGateData;
            this.pulseData = pulseData;
            this.rangePulseRealParts = realParts;
            this.rangePulseImagParts = imagParts;
        }

        public void setTimeVaryingDopplerSpectrum(int dopplerFreqLength, int timeLength,
                                                  List<Double> dopplerFreqData, List<Double> timeData,
                                                  List<Double> spectrumData) {
            this.dopplerFreqLength = dopplerFreqLength;
            this.timeLength = timeLength;
            this.dopplerFreqData = dopplerFreqData;
            this.timeData = timeData;
            this.timeVaryingDopplerSpectrumData = spectrumData;
        }

        // ----------------- Getter 方法 -----------------
        public int getAverageScatteringCoefficientLength() {
            return averageScatteringCoefficientLength;
        }

        public List<Double> getAverageScatteringCoefficientData() {
            return averageScatteringCoefficientData;
        }

        public int getTimeVaryingScatteringCoefficientLength() {
            return timeVaryingScatteringCoefficientLength;
        }

        public List<Double> getTimeVaryingScatteringCoefficientData() {
            return timeVaryingScatteringCoefficientData;
        }

        public int getAmplitudeProbabilityDensityLength() {
            return amplitudeProbabilityDensityLength;
        }

        public List<Double> getAmplitudeProbabilityDensityData() {
            return amplitudeProbabilityDensityData;
        }

        public int getTimeCorrelationLength() {
            return timeCorrelationLength;
        }

        public List<Double> getTimeCorrelationData() {
            return timeCorrelationData;
        }

        public int getDistanceCorrelationLength() {
            return distanceCorrelationLength;
        }

        public List<Double> getDistanceCorrelationData() {
            return distanceCorrelationData;
        }

        public int getDopplerSpectrumLength() {
            return dopplerSpectrumLength;
        }

        public List<Double> getDopplerSpectrumData() {
            return dopplerSpectrumData;
        }

        public int getOneDimensionalImageLength() {
            return oneDimensionalImageLength;
        }

        public List<Double> getOneDimensionalImageData() {
            return oneDimensionalImageData;
        }

        public int getRangeGateLength() {
            return rangeGateLength;
        }

        public int getPulseCountLength() {
            return pulseCountLength;
        }

        public List<Double> getRangeGateData() {
            return rangeGateData;
        }

        public List<Double> getPulseData() {
            return pulseData;
        }

        public List<Double> getRangePulseRealParts() {
            return rangePulseRealParts;
        }

        public List<Double> getRangePulseImagParts() {
            return rangePulseImagParts;
        }

        public int getDopplerFreqLength() {
            return dopplerFreqLength;
        }

        public int getTimeLength() {
            return timeLength;
        }

        public List<Double> getDopplerFreqData() {
            return dopplerFreqData;
        }

        public List<Double> getTimeData() {
            return timeData;
        }

        public List<Double> getTimeVaryingDopplerSpectrumData() {
            return timeVaryingDopplerSpectrumData;
        }
    }

    // ===================== 测试方法 =====================

    public static void main(String[] args) {
        // 文件路径
        String filePath = "D:\\项目\\环境预览\\【内部】BIN\\【内部】20240518095456_YS_SS3_UW_Ku_HH_3_SeaEMData.bin";
        SeaEMDataParser parser = new SeaEMDataParser(filePath);

        // 读取文件
        if (parser.readFile()) {
            // 解析数据
            SeaEMParseResult result = parser.parse();
            if (result != null) {
                // 打印解析结果（可根据需求扩展输出逻辑）
                System.out.println("===== 电磁特性数据解析结果 =====");

                // 1. 平均散射系数
                System.out.println("\n【平均散射系数】");
                System.out.printf("数据长度: %d%n", result.getAverageScatteringCoefficientLength());
                System.out.printf("数据: %s%n", result.getAverageScatteringCoefficientData());

                // 2. 时变散射系数
                System.out.println("\n【时变散射系数】");
                System.out.printf("数据长度: %d%n", result.getTimeVaryingScatteringCoefficientLength());
                System.out.printf("数据: %s%n", result.getTimeVaryingScatteringCoefficientData());

                // 3. 幅度概率密度
                System.out.println("\n【幅度概率密度】");
                System.out.printf("数据长度: %d%n", result.getAmplitudeProbabilityDensityLength());
                System.out.printf("数据: %s%n", result.getAmplitudeProbabilityDensityData());

                // 4. 时间相关特性
                System.out.println("\n【时间相关特性】");
                System.out.printf("数据长度: %d%n", result.getTimeCorrelationLength());
                System.out.printf("数据: %s%n", result.getTimeCorrelationData());

                // 5. 距离相关特性
                System.out.println("\n【距离相关特性】");
                System.out.printf("数据长度: %d%n", result.getDistanceCorrelationLength());
                System.out.printf("数据: %s%n", result.getDistanceCorrelationData());

                // 6. 多普勒谱
                System.out.println("\n【多普勒谱】");
                System.out.printf("数据长度: %d%n", result.getDopplerSpectrumLength());
                System.out.printf("数据: %s%n", result.getDopplerSpectrumData());

                // 7. 一维图像
                System.out.println("\n【一维图像】");
                System.out.printf("数据长度: %d%n", result.getOneDimensionalImageLength());
                System.out.printf("数据: %s%n", result.getOneDimensionalImageData());

                // 8. 距离-脉冲
                System.out.println("\n【距离-脉冲】");
                System.out.printf("距离门长度: %d%n", result.getRangeGateLength());
                System.out.printf("脉冲数长度: %d%n", result.getPulseCountLength());
                System.out.printf("距离门数据: %s%n", result.getRangeGateData());
                System.out.printf("脉冲数数据: %s%n", result.getPulseData());

                // 格式化输出距离-脉冲的复数数据
                System.out.println("距离-脉冲复数数据 (前10个样本):");
                int m = result.getRangeGateLength();
                int n = result.getPulseCountLength();
                int maxDisplay = Math.min(10, m * n);

                for (int i = 0; i < maxDisplay; i++) {
                    double real = result.getRangePulseRealParts().get(i);
                    double imag = result.getRangePulseImagParts().get(i);
                    System.out.printf("样本%d: %.6f + %.6fi%n", i, real, imag);
                }

                // 9. 时变多普勒谱
                System.out.println("\n【时变多普勒谱】");
                System.out.printf("多普勒频率长度: %d%n", result.getDopplerFreqLength());
                System.out.printf("时间长度: %d%n", result.getTimeLength());
                System.out.printf("多普勒频率数据: %s%n", result.getDopplerFreqData());
                System.out.printf("时间数据: %s%n", result.getTimeData());

                // 格式化输出时变多普勒谱数据（显示前10个样本）
                System.out.println("多普勒谱密度数据 (前10个样本):");
                List<Double> spectrumData = result.getTimeVaryingDopplerSpectrumData();
                maxDisplay = Math.min(10, spectrumData.size());

                for (int i = 0; i < maxDisplay; i++) {
                    System.out.printf("谱密度%d: %.6f%n", i, spectrumData.get(i));
                }
            }
        }
    }
}